package org.example.aienglishapp.service.login;

import org.example.aienglishapp.dto.login.RoleDTO;
import org.example.aienglishapp.entity.login.User;
import org.example.aienglishapp.entity.login.UserProfile;
import org.example.aienglishapp.mapper.login.RoleMapper;
import org.example.aienglishapp.mapper.login.UserMapper;
import org.example.aienglishapp.mapper.login.UserProfileMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;
import java.util.NoSuchElementException;

import lombok.extern.slf4j.Slf4j;

/**
 * @author xlj
 * @since 2024-10-1
 * @version 1.0
 */
@Slf4j
@Service
@Component
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserProfileMapper userProfileMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    private static final Logger logger = LoggerFactory.getLogger("com.example.Myclass");

    /**
     * 检查表是否存在。
     *
     * @param tableName 表名
     * @return 如果表存在则返回true，否则返回false。
     */
    public boolean checkTableExists(String tableName) {
        try {
            return userMapper.checkTableExists(tableName);
        } catch (Exception e) {
            log.error("检查表时发生错误: {}", tableName, e);
            return false;
        }
    }

    /**
     * 根据用户状态获取用户列表。
     *
     * @param userStatus 用户状态
     * @return 符合条件的用户列表。
     */
    public List<User> getUsersByStatus(Integer userStatus) {
        return userMapper.findByUserStatus(userStatus);
    }

    /**
     * 获取所有用户的方法（取消分页，直接查询所有）。
     *
     * @return 所有用户的列表。
     */
    public List<User> getAllUsers() {
        return userMapper.findAll();
    }

    /**
     * 更新用户状态的方法。
     *
     * @param userId 用户ID
     * @param userStatus 新的用户状态
     */
    @Transactional
    public void updateUserStatus(Long userId, Integer userStatus) {
        log.info("更新用户 ID: {} 状态为: {}", userId, userStatus);
        userMapper.updateUserStatus(userId, userStatus);
    }

    /**
     * 注册用户。
     *
     * @param user 要注册的用户信息
     */
    @Transactional
    public void registerUser(User user) {
        if (checkTableExists("users")) {
            user.setRegistrationTime(new Timestamp(System.currentTimeMillis()));
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String hashedPassword = passwordEncoder.encode(user.getUserPassword());
            user.setUserPassword(hashedPassword);
            user.setUserStatus(1);
            user.setUserPoints(0);
            user.setExperiencePoints(0);
            userMapper.insert(user);
            log.info("用户注册成功: {}", user.getUserName());

            // 为用户分配默认角色
            assignRoleToUser(user.getUserId(), 2);
        } else {
            log.warn("无法注册用户，表不存在。");
        }
    }

    /**
     * 检查用户名是否存在。
     *
     * @param username 用户名
     * @return 如果用户名存在则返回true，否则返回false。
     */
    public boolean checkUsernameExists(String username) {
        return userMapper.existsByUserName(username);
    }

    /**
     * 检查手机号是否存在。
     *
     * @param phoneNumber 手机号
     * @return 如果手机号存在则返回true，否则返回false。
     */
    public boolean checkPhoneNumberExists(String phoneNumber) {
        if (checkTableExists("users")) {
            return userMapper.existsByPhoneNumber(phoneNumber);
        }
        return false;
    }

    /**
     * 根据用户名查找用户。
     *
     * @param username 用户名
     * @return 找到的用户对象或null。
     */
    public User findByUsername(String username) {
        if (checkTableExists("users")) {
            return userMapper.findByUserName(username);
        }
        return null;
    }

    /**
     * 根据手机号码查找用户。
     *
     * @param phoneNumber 手机号
     * @return 找到的用户对象或null。
     */
    public User findByPhoneNumber(String phoneNumber) {
        if (checkTableExists("users")) {
            return userMapper.findByPhoneNumber(phoneNumber);
        }
        return null;
    }

    /**
     * 保存用户资料。
     *
     * @param userProfile 用户资料
     */
    @Transactional
    public void saveUserProfile(UserProfile userProfile) {
        userProfileMapper.update(userProfile);
    }

    /**
     * 删除多个用户及其相关信息。
     *
     * @param userIds 要删除的用户ID列表
     */
    @Transactional
    public void deleteUsers(List<Long> userIds) {
        for (Long userId : userIds) {
            // 1. 先删除用户的角色关联
            roleMapper.deleteRolesByUserId(userId);

            // 2. 删除用户的资料
            userProfileMapper.deleteByUserId(userId);

            // 3. 最后删除用户本身
            userMapper.deleteUserById(userId);
        }
    }

    /**
     * 获取用户资料。
     *
     * @param userId 用户ID
     * @return 用户资料对象。
     */
    public UserProfile getUserProfile(Long userId) {
        return userProfileMapper.findByUserId(userId);
    }

    /**
     * 更新用户的方法。
     *
     * @param user 要更新的用户信息
     */
    @Transactional
    public void updateUser(User user) {
        userMapper.update(user);
    }

    /**
     * 为用户分配角色。
     *
     * @param userId 用户ID
     * @param roleId 角色ID
     */
    public void assignRoleToUser(Long userId, Integer roleId) {
        roleMapper.insertUserRole(userId, roleId);
        log.info("为用户 ID: {} 分配角色 ID: {}", userId, roleId);
    }

    /**
     * 获取用户角色。
     *
     * @param userId 用户ID
     * @return 用户角色列表。
     */
    public List<RoleDTO> getUserRoles(Long userId) {
        return roleMapper.getUserRolesByUserId(userId);
    }

    /**
     * 更新用户角色。
     *
     * @param userId 用户ID
     * @param roleIds 新的角色ID列表
     */
    @Transactional
    public void updateUserRoles(Long userId, List<Integer> roleIds) {
        // 首先清除用户的现有角色
        roleMapper.deleteRolesByUserId(userId);

        // 然后为用户分配新的角色
        for (Integer roleId : roleIds) {
            assignRoleToUser(userId, roleId);
        }
    }

    /**
     * 更新用户昵称。
     *
     * @param userId 用户ID
     * @param nickname 新的昵称
     */
    public void updateUserNickname(Long userId, String nickname) {
        User user = userMapper.findByIdWithProfile(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        UserProfile userProfile = user.getUserProfile();
        if (userProfile == null) {
            throw new IllegalStateException("用户资料未找到");
        }

        // 更新昵称
        nickname = nickname.trim();
        log.info("更新前的昵称: {}", userProfile.getNickname());
        userProfile.setNickname(nickname);
        log.info("即将插入的昵称值: {}", userProfile.getNickname());
        userProfileMapper.update(userProfile);
    }

    /**
     * 更新用户性别。
     *
     * @param userId 用户ID
     * @param genderStr 性别字符串
     */
    @Transactional
    public void updateUserGender(Long userId, String genderStr) {
        User user = userMapper.findByIdWithProfile(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        UserProfile userProfile = user.getUserProfile();
        if (userProfile == null) {
            throw new IllegalStateException("用户资料未找到");
        }
        // 处理传入的性别值
        genderStr = genderStr.trim();
        // 设置并验证新的性别值
        userProfile.setGender(genderStr);
        try {
            userProfileMapper.update(userProfile);
        } catch (Exception e) {
            log.error("更新用户性别失败，用户ID: {}", userId, e);
            throw e;
        }
    }

    /**
     * 更新用户年龄。
     *
     * @param userId 用户ID
     * @param age 新的年龄
     */
    @Transactional
    public void updateUserAge(Long userId, Integer age) {
        User user = userMapper.findByIdWithProfile(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        UserProfile userProfile = user.getUserProfile();
        if (userProfile == null) {
            throw new IllegalStateException("用户资料未找到");
        }

        // 更新年龄
        userProfile.setAge(age);
        userProfileMapper.update(userProfile);
    }

    /**
     * 更新用户签名。
     *
     * @param userId 用户ID
     * @param signature 新的签名
     */
    @Transactional
    public void updateUserSignature(Long userId, String signature) {
        User user = userMapper.findByIdWithProfile(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        UserProfile userProfile = user.getUserProfile();
        if (userProfile == null) {
            throw new IllegalStateException("用户资料未找到");
        }

        // 更新签名
        signature = signature.trim();
        userProfile.setSignature(signature);
        userProfileMapper.update(userProfile);
    }

    /**
     * 更新用户名。
     *
     * @param userId 用户ID
     * @param username 新的用户名
     */
    @Transactional
    public void updateUserUsername(Long userId, String username) {
        User user = userMapper.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        // 更新用户名
        username = username.trim();
        user.setUserName(username);
        userMapper.update(user);
    }

    /**
     * 更新用户密码。
     *
     * @param userId 用户ID
     * @param newPassword 新的密码
     */
    @Transactional
    public void updateUserPassword(Long userId, String newPassword) {
        User user = userMapper.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        log.info("正在更新该用户密码: {}", user);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String hashedPassword = passwordEncoder.encode(newPassword);
        log.info("加密后的新密码: {}", hashedPassword);
        user.setUserPassword(hashedPassword);
        userMapper.update(user);
        log.info("用户密码更新成功，用户 ID: {}", userId);
    }

    /**
     * 更新用户手机号码。
     *
     * @param userId 用户ID
     * @param newPhoneNumber 新的手机号码
     */
    @Transactional
    public void updateUserPhoneNumber(Long userId, String newPhoneNumber) {
        // 检查新手机号是否存在
        if (checkPhoneNumberExists(newPhoneNumber)) {
            log.warn("该手机号已被其他用户使用");
            throw new IllegalArgumentException("该手机号已被其他用户使用");
        }

        // 根据用户 ID 查找用户
        User user = userMapper.findById(userId)
                .orElseThrow(() -> {
                    log.warn("用户未找到，ID: {}", userId);
                    return new NoSuchElementException("用户未找到");
                });

        log.info("即将更新id为{}的用户的手机号码为: {}", userId, newPhoneNumber);

        // 更新手机号
        user.setPhone(newPhoneNumber);
        userMapper.update(user);

        log.info("用户手机号码更新成功，用户 ID: {}", userId);
    }

    /**
     * 注销用户。
     *
     * @param userId 用户ID
     * @param password 用户密码
     */
    @Transactional
    public void logoutUser(Long userId, String password) {
        log.info("开始注销用户，用户 ID: {}", userId);

        User user = userMapper.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户未找到"));

        log.info("找到用户: {}", user);

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (passwordEncoder.matches(password, user.getUserPassword())) {
            log.info("密码验证通过，开始注销用户");
            updateUserStatus(userId, 0);
            log.info("用户注销成功，用户 ID: {}", userId);
        } else {
            throw new IllegalArgumentException("密码不正确");
        }
    }
}